﻿using System;
using System.Xml;

namespace FESSC_MESSAGE
{
    public class Msg
    {
        public enum TYPE
        {
            REQUEST,
            RESPONSE
        }

        public XmlDocument xd;
        protected XmlElement root;
        protected XmlElement header;
        protected bool isReq;

        public Msg(bool isRequest = true)
        {
            xd = new XmlDocument();
            isReq = isRequest;
            xd.AppendChild(xd.CreateXmlDeclaration("1.0", "UTF-8", null));
            root = newElement(isReq ? "rq" : "rs");
            xd.AppendChild(root);
        }

        public Msg(string xml)
        {
            xd = new XmlDocument();
            xd.LoadXml(xml);
        }

        public XmlElement add(XmlNode target, string nodeName, string nodeText = "")
        {
            var node = newElement(nodeName, nodeText);
            target.AppendChild(node);
            return node;
        }

        public XmlElement add(string nodeName, string nodeText = "")
        {
            return add(root, nodeName, nodeText);
        }

        public XmlElement newElement(string name, string text = "")
        {
            var ret = xd.CreateElement(name);
            if (!string.IsNullOrEmpty(text)) ret.InnerText = text;
            return ret;
        }

        /**
         * sender:0=Self
         * recver:0=Server
         * token:String Length=16
         */
        public void setHeader(string operation, int sender, int recver, string token = "")
        {
            header = add(root, "header");
            add(header, "operation", operation);
            add(header, "sender", sender.ToString());
            add(header, "recver", recver.ToString());
            add(header, "token", token);
        }

        public void setFirstValueByName(string name, string value)
        {
            var el = xd.GetElementsByTagName(name);
            if (el.Count > 0) el[0].InnerText = value;
        }

        public void setFirstValueByName(string name, int value)
        {
            setFirstValueByName(name, value.ToString());
        }

        public void setValueByName(string name, string value)
        {
            var el = xd.GetElementsByTagName(name);
            if (el.Count > 0)
            {
                foreach (XmlNode elm in el)
                {
                    elm.InnerText = value;
                }
            }
        }

        public void setValueByName(string name, int value)
        {
            setValueByName(name, value.ToString());
        }

        public void setToken(string token)
        {
            setFirstValueByName("token", token);
        }

        public void setRsCode(string code = "OK")
        {
            add(header, "rscode", code);
            add(header, "rsdesc", RspCode.get(code));
        }

        public string getRsCode()
        {
            string ret = string.Empty;
            try
            {
                ret = getValueByXpath("/rs/header/rscode");
            }
            catch (Exception)
            {
                ret = string.Empty;
            }
            return ret;
        }

        public string getRsDesc()
        {
            string ret = string.Empty;
            try
            {
                ret = getValueByXpath("/rs/header/rsdesc");
            }
            catch (Exception)
            {
                ret = string.Empty;
            }
            return ret;
        }

        public string getValueByXpath(string xpath, int index = 0)
        {
            string ret = string.Empty;
            if (index == 0)
            {
                ret = xd.SelectSingleNode(xpath).InnerText;
            }
            else if (index > 0)
            {
                ret = xd.SelectNodes(xpath)[index].InnerText;
            }
            return ret;
        }

        public string[] getValuesByXpath(string xpath)
        {
            string[] ret;
            var n = xd.SelectNodes(xpath);
            ret = new string[n.Count];
            int i = 0;
            foreach (XmlElement sn in n)
            {
                ret[i++] = sn.InnerText;
            }
            return ret;
        }

        public string getRootName()
        {
            return xd.FirstChild.NextSibling.Name;
        }

        public string getRqOperationCode()
        {
            return getValueByXpath("/rq/header/operation");
        }

        public override string ToString()
        {
            string ret = string.Empty;
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            XmlTextWriter wr = new XmlTextWriter(ms, System.Text.Encoding.Default);
            wr.Formatting = Formatting.Indented;
            xd.Save(wr);
            System.IO.StreamReader sr = new System.IO.StreamReader(ms, System.Text.Encoding.Default);
            ms.Position = 0;
            ret = sr.ReadToEnd();
            sr.Close();
            ms.Close();
            wr.Close();
            return ret;
        }
    }
}
